import matplotlib.pyplot as plt
import matplotlib.dates as mdates
from datetime import datetime
import numpy as np
import matplotlib as mpl
from numpy.polynomial.polynomial import Polynomial

# 设置支持中文的字体
plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei', 'Arial Unicode MS']  # 设置支持中文的字体
plt.rcParams['axes.unicode_minus'] = False  # 正确显示负号


def plot_time_series():
    # 更新后的数据（日期、碳量、体重）
    dates = ['6/16', '6/17', '6/18', '6/19', '6/20', '6/21', '6/22', '6/23', '6/24', '6/25', '6/26', '6/27', '6/28',
             '6/29', '6/30', '7/01', '7/02', '7/03', '7/04', '7/05', '7/06', '7/07', '7/08', '7/09', '7/10', '7/11', '7/12', '7/13' , '7/14' , '7/15', '7/16']  # 更新到7月14日
    carbon = [150, 115, 150, 121, 300, 134, 260, 130, 130, 100, 70, 400, 110, 110, 110, 400, 65, 70, 70, 400, 70,
              70, 70, 400, 70, 80, 80, 400, 80 ,90, 90]  # 更新碳量数据
    values = [76.6, 75.9, 75.5, 75.5, 76.25, 75.7, 76.3, 75.4, 75.7, 75.35, 75.30, 75.25, 74.80, 74.55, 75.15,
              75.45, 74.65, 74.60, 74.10, 73.90, 74.00, 73.10, 72.5, 74.60, 73.60, 72.6, 72.35, 73.00, 72.45, 72.10,71.65]  # 更新体重数据    # 将日期字符串转换为datetime对象
    date_objs = [datetime.strptime(date + '/2025', '%m/%d/%Y') for date in dates]
    # 创建数值型日期，用于绘图
    x = [mdates.date2num(date) for date in date_objs]
    # 创建从0开始的整数序列用于拟合
    x_days = np.arange(len(x))

    # === 体重数据拟合 ===
    # 使用3次多项式拟合体重数据
    coeffs = np.polyfit(x_days, values, 3)
    poly = np.poly1d(coeffs)
    trend_line = poly(x_days)

    # 计算拟合优度R²
    residuals = np.array(values) - trend_line
    ss_res = np.sum(residuals ** 2)
    ss_tot = np.sum((np.array(values) - np.mean(values)) ** 2)
    r_squared = 1 - (ss_res / ss_tot)

    # 设置图表
    fig = plt.figure(figsize=(15, 10))  # 稍微增加高度以容纳更多数据
    gs = fig.add_gridspec(2, 1, height_ratios=[1, 6])  # 创建2行网格（进度条+主图表）

    # === 1. 减脂进度条 ===
    progress_ax = fig.add_subplot(gs[0])
    # 进度计算
    start_weight = 76.6
    target_weight = 70
    current_weight = values[-1]  # 最后一天的体重
    total_loss = start_weight - target_weight
    current_loss = start_weight - current_weight
    progress = current_loss / total_loss

    # 绘制进度条
    progress_ax.barh(['进度'], [1], color='lightgray', height=0.3)  # 背景条
    progress_ax.barh(['进度'], [progress], color='#4CAF50', height=0.3)  # 进度条
    progress_ax.text(progress / 2, 0, f'{progress:.1%}',
                     ha='center', va='center', color='white', fontsize=12, fontweight='bold')
    progress_ax.set_xlim(0, max(1, progress + 0.1))  # 动态调整x轴范围，确保进度条显示完整
    progress_ax.set_xticks([])
    progress_ax.set_yticks([])
    progress_ax.set_title(f'减脂进度: {current_loss:.2f}kg/{total_loss:.2f}kg (目标: {target_weight}kg)',
                          fontsize=14, pad=20)

    # === 2. 主图表 ===
    ax1 = fig.add_subplot(gs[1])

    # 绘制碳量（左侧y轴）
    color = 'tab:blue'
    ax1.set_xlabel('日期')
    ax1.set_ylabel('碳水量 (g)', color=color)
    carbon_bars = ax1.bar(x, carbon, color=color, alpha=0.6, label='碳量', width=0.5)
    ax1.tick_params(axis='y', labelcolor=color)
    ax1.grid(True, which='both', axis='y', linestyle='--', linewidth=0.5)

    # 创建第二个y轴（右侧）
    ax2 = ax1.twinx()
    color = 'tab:red'
    ax2.set_ylabel('体重（kg）', color=color)
    weight_line, = ax2.plot(x, values, color=color, linestyle='-', marker='o', markersize=6, linewidth=2, label='体重')

    # 添加拟合曲线（趋势线）
    trend_color = 'darkgreen'
    trend_line, = ax2.plot(x, trend_line, color=trend_color, linestyle='-', linewidth=2.5,
                           label=f'趋势线')  # 显示R²值

    # 添加目标体重线
    target_line = ax2.axhline(y=target_weight, color='purple', linestyle='--', alpha=0.7, label='目标体重')
    ax2.text(x[-1], target_weight + 0.1, f'目标: {target_weight}kg',
             color='purple', ha='right', va='bottom', fontsize=9)

    # 设置日期格式
    date_form = mdates.DateFormatter("%m/%d")
    ax1.xaxis.set_major_formatter(date_form)
    ax1.xaxis.set_major_locator(mdates.DayLocator(interval=2))  # 每2天显示一个刻度

    # 添加图例
    lines1 = [carbon_bars]
    labels1 = ['碳量']
    lines2 = [weight_line, trend_line, target_line]
    labels2 = ['体重', f'趋势线', '目标体重']
    ax2.legend(lines1 + lines2, labels1 + labels2, loc='upper left')

    # 设置图表标题
    plt.title(f'碳水量与体重变化趋势 (6.16-7.16)---{len(values)}days', fontsize=16, pad=20)  # 更新日期范围

    # 添加网格线
    ax1.grid(True, linestyle='--', alpha=0.7)

    # 自动调整布局
    fig.tight_layout()
    plt.show()


# 运行函数
plot_time_series()